﻿using AutoMapper;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using WMS.FC.Domain.DomainObject.Station;
using WMS.FC.Domain.DomainObject.System;
using WMS.FC.Domain.PersistenceObject.Business;
using WMS.FC.Domain.Repository;
using WMS.FC.Domain.Service.Station.Interface;
using WMS.FC.Domain.Service.System;
using WMS.FC.Domain.Service.Tray.Interface;

namespace WMS.FC.Domain.Service.Station
{
    public class GetTrayTargetStationService : ServiceBase, IGetTrayTargetStationService
    {
        protected readonly ITrayRepository trayRepository;
        protected readonly IStationRepository stationRepository;
        protected readonly IPileTrayService pileTrayService;
        protected readonly ITechnologyRepository technologyRepository;
        protected readonly IGetTrayProductLineService getTrayProductLineService;
        protected readonly IAutoBindTrayService autoBindTrayService;
        protected readonly IGetTrayInfoService getTrayInfoService;

        public GetTrayTargetStationService(
            ILogger<ServiceBase> logger,
            IOptions<WmsSettings> options,
            IMapper mapper,
            IStationRepository stationRepository,
            ITrayRepository trayRepository,
            IPileTrayService pileTrayService,
            IGetTrayProductLineService getTrayProductLineService,
            ITechnologyRepository technologyRepository,
            IAutoBindTrayService autoBindTrayService,
            IGetTrayInfoService getTrayInfoService)
            : base(logger, options, mapper)
        {
            this.stationRepository = stationRepository;
            this.trayRepository = trayRepository;
            this.pileTrayService = pileTrayService;
            this.getTrayProductLineService = getTrayProductLineService;
            this.technologyRepository = technologyRepository;
            this.autoBindTrayService = autoBindTrayService;
            this.getTrayInfoService = getTrayInfoService;
        }

        public async Task<ActionResult<TargetStationDO>> GetTrayTargetStation(string? trayBarcode1, string? trayBarcode2, string? trayBarcode3, string? stationCode, UserInfo userInfo)
        {
            var result = new ActionResult<TargetStationDO>("获取托盘目标站台");
            try
            {
                if (string.IsNullOrWhiteSpace(trayBarcode1))
                    return result.ArgumentError("托盘条码不能为空");

                if (string.IsNullOrWhiteSpace(stationCode))
                    return result.ArgumentError("站台编码不能为空");

                var getTrayProductLineResult = await getTrayProductLineService.GetTrayProductLine(trayBarcode1);
                if (!getTrayProductLineResult.IsSuccess)
                    return result.Fail(getTrayProductLineResult);

                var lineCode = getTrayProductLineResult.Data!;
                var stationPO = await stationRepository.GetStation(lineCode, stationCode);
                if (stationPO == null)
                    return result.BusinessError($"产线编码:({lineCode}),站台编码:({stationCode}),站台数据未找到");

                if (string.IsNullOrWhiteSpace(stationPO.TypeCode))
                    return result.BusinessError($"产线编码:({lineCode}),站台编码:({stationCode}),站台类型未设置");

                var toStationList = await stationRepository.GetToStationList(lineCode, stationCode);
                var bussinessList = stationPO.TypeCode.Split(",", StringSplitOptions.RemoveEmptyEntries & StringSplitOptions.TrimEntries);
                if (bussinessList.Contains("StationType_AutoBind"))
                {
                    var autoBindTrayResult = await autoBindTrayService.AutoBindTray(lineCode, trayBarcode1, stationCode, userInfo);
                    if (!autoBindTrayResult.IsSuccess)
                        return result.Fail(autoBindTrayResult);
                }

                if (bussinessList.Contains("StationType_BindContainer"))
                {
                    var pileTrayResult = await pileTrayService.PileTray(trayBarcode1, trayBarcode2, trayBarcode3, userInfo);
                    if (!pileTrayResult.IsSuccess)
                        return result.Fail(pileTrayResult);
                }

                if (bussinessList.Contains("StationType_ProductOffline"))
                {

                }

                var getTrayInfoResul = await getTrayInfoService.GetTrayInfo(trayBarcode1, true, true, true, true, true, true, userInfo);
                if (!getTrayInfoResul.IsSuccess)
                    return result.Fail(getTrayInfoResul);

                var trayDO = getTrayInfoResul.Data!;
                var cellCount = trayDO.CellList.Count(cell => !string.IsNullOrWhiteSpace(cell.Barcode) && !cell.Barcode.StartsWith(options.Value.FakeCellBarcodePrefix, StringComparison.InvariantCultureIgnoreCase));
                var fakeCellCount = trayDO.CellList.Count(cell => !string.IsNullOrWhiteSpace(cell.Barcode) && cell.Barcode.StartsWith(options.Value.FakeCellBarcodePrefix, StringComparison.InvariantCultureIgnoreCase));
                var data = new TargetStationDO()
                {
                    Tray = trayDO,
                    IsNg = trayDO.CellList.Any(cell => !string.IsNullOrWhiteSpace(cell.NgCode)),
                    IsException = trayDO.CellList.Count(cell => !string.IsNullOrWhiteSpace(cell.NgCode)) == cellCount && cellCount > 0 || trayDO.CurrentTray.StateCode == "TrayState_Exception",
                    IsFull = (cellCount + fakeCellCount) == trayDO.TrayMaterial.FillQuantity,
                    IsEmpty = (cellCount + fakeCellCount) == 0,
                    IsAllFake = cellCount == 0 && fakeCellCount > 0,
                    GoodsType = $"{((cellCount + fakeCellCount) == 0 ? "1" : "2")}{trayDO.TrayList!.Count}"
                };

                if (data.IsEmpty)
                {
                    data.TargetStationCode = "";
                }
                else if (data.IsAllFake)
                {
                    if (toStationList.Any(station => station.TypeCode.Contains("StationType_UnbindCell")))
                    {
                        data.TargetStationCode = toStationList.First(station => station.TypeCode.Contains("StationType_UnbindCell")).Code;
                    }
                    else
                    {
                        data.IsException = true;
                    }
                }
                else
                {
                    var lineTechnologyProcessRoutePO = await technologyRepository.GetLineTechnologyProcessRoute(lineCode, getTrayInfoResul.Data!.CurrentTray.TechnologyProcessCode);
                    if (lineTechnologyProcessRoutePO == null)
                        return result.BusinessError($"产线编码:({lineCode}),工艺工序:({getTrayInfoResul.Data!.CurrentTray.TechnologyProcessCode}),工艺工序路径数据未找到");

                    if (data.IsException && toStationList.Any(station => station.TypeCode.Contains("StationType_Manual")))
                    {
                        data.TargetStationCode = toStationList.First(station => station.TypeCode.Contains("StationType_Manual")).Code;
                    }
                    else if ((data.IsNg || (data.IsFake && !trayDO.CurrentTechnologyProcess!.IsNeedFakeCell)) && toStationList.Any(station => station.TypeCode.Contains("StationType_UnbindCell")))
                    {
                        data.TargetStationCode = toStationList.First(station => station.TypeCode.Contains("StationType_UnbindCell")).Code;
                    }
                    else if (!data.IsFull && trayDO.CurrentTechnologyProcess!.IsNeedFakeCell && toStationList.Any(station => station.TypeCode.Contains("StationType_BindCell")))
                    {
                        data.TargetStationCode = toStationList.First(station => station.TypeCode.Contains("StationType_BindCell")).Code;
                    }
                    else
                    {
                        data.TargetStationCode = lineTechnologyProcessRoutePO.StationCode;
                    }
                }

                result.Data = data;
            }
            catch (Exception ex)
            {
                return result.Exception(ex);
            }

            return result;
        }
    }
}
